<!doctype html>

<html>
<head>
  <link rel="shortcut icon" href="static/images/favicon.ico" type="image/x-icon">
  <title>bidi.js (Closure Library API Documentation - JavaScript)</title>
  <link rel="stylesheet" href="static/css/base.css">
  <link rel="stylesheet" href="static/css/doc.css">
  <link rel="stylesheet" href="static/css/sidetree.css">
  <link rel="stylesheet" href="static/css/prettify.css">

  <script>
     var _staticFilePath = "static/";
  </script>

  <script src="static/js/doc.js">
  </script>

  <meta charset="utf8">
</head>

<body onload="prettyPrint()">

<div id="header">
  <div class="g-section g-tpl-50-50 g-split">
    <div class="g-unit g-first">
      <a id="logo" href="index.html">Closure Library API Documentation</a>
    </div>

    <div class="g-unit">
      <div class="g-c">
        <strong>Go to class or file:</strong>
        <input type="text" id="ac">
      </div>
    </div>
  </div>
</div>

<div class="clear"></div>

<h2><a href="closure_goog_i18n_bidi.js.html">bidi.js</a></h2>

<pre class="prettyprint lang-js">
<a name="line1"></a>// Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
<a name="line2"></a>// you may not use this file except in compliance with the License.
<a name="line3"></a>// You may obtain a copy of the License at
<a name="line4"></a>//
<a name="line5"></a>//     http://www.apache.org/licenses/LICENSE-2.0
<a name="line6"></a>//
<a name="line7"></a>// Unless required by applicable law or agreed to in writing, software
<a name="line8"></a>// distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
<a name="line9"></a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a name="line10"></a>// See the License for the specific language governing permissions and
<a name="line11"></a>// limitations under the License.
<a name="line12"></a>
<a name="line13"></a>// Copyright 2007 Google Inc. All Rights Reserved.
<a name="line14"></a>
<a name="line15"></a>/**
<a name="line16"></a> * @fileoverview Utility functions for supporting Bidi issues.
<a name="line17"></a> */
<a name="line18"></a>
<a name="line19"></a>
<a name="line20"></a>/**
<a name="line21"></a> * Namespace for bidi supporting functions.
<a name="line22"></a> */
<a name="line23"></a>goog.provide(&#39;goog.i18n.bidi&#39;);
<a name="line24"></a>
<a name="line25"></a>
<a name="line26"></a>
<a name="line27"></a>/**
<a name="line28"></a> * Unicode formatting characters and directionality string constants.
<a name="line29"></a> * @enum {string}
<a name="line30"></a> */
<a name="line31"></a>goog.i18n.bidi.Format = {
<a name="line32"></a>  /** Unicode &quot;Left-To-Right Embedding&quot; (LRE) character. */
<a name="line33"></a>  LRE: &#39;\u202A&#39;,
<a name="line34"></a>  /** Unicode &quot;Right-To-Left Embedding&quot; (RLE) character. */
<a name="line35"></a>  RLE: &#39;\u202B&#39;,
<a name="line36"></a>  /** Unicode &quot;Pop Directional Formatting&quot; (PDF) character. */
<a name="line37"></a>  PDF: &#39;\u202C&#39;,
<a name="line38"></a>  /** Unicode &quot;Left-To-Right Mark&quot; (LRM) character. */
<a name="line39"></a>  LRM: &#39;\u200E&#39;,
<a name="line40"></a>  /** Unicode &quot;Right-To-Left Mark&quot; (RLM) character. */
<a name="line41"></a>  RLM: &#39;\u200F&#39;
<a name="line42"></a>};
<a name="line43"></a>
<a name="line44"></a>
<a name="line45"></a>/**
<a name="line46"></a> * Directionality enum.
<a name="line47"></a> * @enum {number}
<a name="line48"></a> */
<a name="line49"></a>goog.i18n.bidi.Dir = {
<a name="line50"></a>  RTL: -1,
<a name="line51"></a>  UNKNOWN: 0,
<a name="line52"></a>  LTR: 1
<a name="line53"></a>};
<a name="line54"></a>
<a name="line55"></a>
<a name="line56"></a>/**
<a name="line57"></a> * &#39;right&#39; string constant.
<a name="line58"></a> * @type {string}
<a name="line59"></a> */
<a name="line60"></a>goog.i18n.bidi.RIGHT = &#39;right&#39;;
<a name="line61"></a>
<a name="line62"></a>
<a name="line63"></a>/**
<a name="line64"></a> * &#39;left&#39; string constant.
<a name="line65"></a> * @type {string}
<a name="line66"></a> */
<a name="line67"></a>goog.i18n.bidi.LEFT = &#39;left&#39;;
<a name="line68"></a>
<a name="line69"></a>
<a name="line70"></a>/**
<a name="line71"></a> * Convert a directionality given in various formats to a goog.i18n.bidi.Dir
<a name="line72"></a> * constant. Useful for interaction with different standards of directionality
<a name="line73"></a> * representation.
<a name="line74"></a> *
<a name="line75"></a> * @param {goog.i18n.bidi.Dir|number|boolean} givenDir Directionality given in
<a name="line76"></a> *     one of the following formats:
<a name="line77"></a> *     1. A goog.i18n.bidi.Dir constant.
<a name="line78"></a> *     2. A number (positive = LRT, negative = RTL, 0 = unknown).
<a name="line79"></a> *     3. A boolean (true = RTL, false = LTR).
<a name="line80"></a> * @return {goog.i18n.bidi.Dir} A goog.i18n.bidi.Dir constant matching the given
<a name="line81"></a> *     directionality.
<a name="line82"></a> */
<a name="line83"></a>goog.i18n.bidi.toDir = function(givenDir) {
<a name="line84"></a>  if (typeof givenDir == &#39;number&#39;) {
<a name="line85"></a>    return givenDir &gt; 0 ? goog.i18n.bidi.Dir.LTR :
<a name="line86"></a>        givenDir &lt; 0 ? goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.UNKNOWN;
<a name="line87"></a>  } else {
<a name="line88"></a>    return givenDir ? goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR;
<a name="line89"></a>  }
<a name="line90"></a>};
<a name="line91"></a>
<a name="line92"></a>
<a name="line93"></a>/**
<a name="line94"></a> * A practical pattern to identify strong LTR characters. This pattern is not
<a name="line95"></a> * theoretically correct according to the Unicode standard. It is simplified for
<a name="line96"></a> * performance and small code size.
<a name="line97"></a> * @type {string}
<a name="line98"></a> * @private
<a name="line99"></a> */
<a name="line100"></a>goog.i18n.bidi.ltrChars_ =
<a name="line101"></a>    &#39;A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF&#39; +
<a name="line102"></a>    &#39;\u2C00-\uFB1C\uFE00-\uFE6F\uFEFD-\uFFFF&#39;;
<a name="line103"></a>
<a name="line104"></a>
<a name="line105"></a>/**
<a name="line106"></a> * A practical pattern to identify strong RTL character. This pattern is not
<a name="line107"></a> * theoretically correct according to the Unicode standard. It is simplified
<a name="line108"></a> * for performance and small code size.
<a name="line109"></a> * @type {string}
<a name="line110"></a> * @private
<a name="line111"></a> */
<a name="line112"></a>goog.i18n.bidi.rtlChars_ = &#39;\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC&#39;;
<a name="line113"></a>
<a name="line114"></a>
<a name="line115"></a>/**
<a name="line116"></a> * Simplified regular expression for an HTML tag (opening or closing) or an HTML
<a name="line117"></a> * escape. We might want to skip over such expressions when estimating the text
<a name="line118"></a> * directionality.
<a name="line119"></a> * @type {RegExp}
<a name="line120"></a> * @private
<a name="line121"></a> */
<a name="line122"></a>goog.i18n.bidi.htmlSkipReg_ = /&lt;[^&gt;]*&gt;|&amp;[^;]+;/g;
<a name="line123"></a>
<a name="line124"></a>
<a name="line125"></a>/**
<a name="line126"></a> * Returns the input text with spaces instead of HTML tags or HTML escapes, if
<a name="line127"></a> * opt_isStripNeeded is true. Else returns the input as is.
<a name="line128"></a> * Useful for text directionality estimation.
<a name="line129"></a> * Note: the function should not be used in other contexts; it is not 100%
<a name="line130"></a> * correct, but rather a good-enough implementation for directionality
<a name="line131"></a> * estimation purposes.
<a name="line132"></a> * @param {string} str The given string.
<a name="line133"></a> * @param {boolean} opt_isStripNeeded Whether to perform the stripping.
<a name="line134"></a> *     Default: false (to retain consistency with calling functions).
<a name="line135"></a> * @return {string} The given string cleaned of HTML tags / escapes.
<a name="line136"></a> * @private
<a name="line137"></a> */
<a name="line138"></a>goog.i18n.bidi.stripHtmlIfNeeded_ = function(str, opt_isStripNeeded) {
<a name="line139"></a>  return opt_isStripNeeded ? str.replace(goog.i18n.bidi.htmlSkipReg_, &#39; &#39;) :
<a name="line140"></a>      str;
<a name="line141"></a>};
<a name="line142"></a>
<a name="line143"></a>
<a name="line144"></a>/**
<a name="line145"></a> * Regular expression to check for RTL characters.
<a name="line146"></a> * @type {RegExp}
<a name="line147"></a> * @private
<a name="line148"></a> */
<a name="line149"></a>goog.i18n.bidi.rtlCharReg_ = new RegExp(&#39;[&#39; + goog.i18n.bidi.rtlChars_ + &#39;]&#39;);
<a name="line150"></a>
<a name="line151"></a>
<a name="line152"></a>/**
<a name="line153"></a> * Regular expression to check for LTR characters.
<a name="line154"></a> * @type {RegExp}
<a name="line155"></a> * @private
<a name="line156"></a> */
<a name="line157"></a>goog.i18n.bidi.ltrCharReg_ = new RegExp(&#39;[&#39; + goog.i18n.bidi.ltrChars_ + &#39;]&#39;);
<a name="line158"></a>
<a name="line159"></a>
<a name="line160"></a>/**
<a name="line161"></a> * Test whether the given string has any RTL characters in it.
<a name="line162"></a> * @param {string} str The given string that need to be tested.
<a name="line163"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line164"></a> *     Default: false.
<a name="line165"></a> * @return {boolean} Whether the string contains RTL characters.
<a name="line166"></a> */
<a name="line167"></a>goog.i18n.bidi.hasAnyRtl = function(str, opt_isHtml) {
<a name="line168"></a>  return goog.i18n.bidi.rtlCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
<a name="line169"></a>      str, opt_isHtml));
<a name="line170"></a>};
<a name="line171"></a>
<a name="line172"></a>
<a name="line173"></a>/**
<a name="line174"></a> * Test whether the given string has any RTL characters in it.
<a name="line175"></a> * @param {string} str The given string that need to be tested.
<a name="line176"></a> * @return {boolean} Whether the string contains RTL characters.
<a name="line177"></a> * @deprecated Use hasAnyRtl.
<a name="line178"></a> */
<a name="line179"></a>goog.i18n.bidi.hasRtlChar = goog.i18n.bidi.hasAnyRtl;
<a name="line180"></a>
<a name="line181"></a>
<a name="line182"></a>/**
<a name="line183"></a> * Test whether the given string has any LTR characters in it.
<a name="line184"></a> * @param {string} str The given string that need to be tested.
<a name="line185"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line186"></a> *     Default: false.
<a name="line187"></a> * @return {boolean} Whether the string contains LTR characters.
<a name="line188"></a> */
<a name="line189"></a>goog.i18n.bidi.hasAnyLtr = function(str, opt_isHtml) {
<a name="line190"></a>  return goog.i18n.bidi.ltrCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
<a name="line191"></a>      str, opt_isHtml));
<a name="line192"></a>};
<a name="line193"></a>
<a name="line194"></a>
<a name="line195"></a>/**
<a name="line196"></a> * Regular expression pattern to check if the first character in the string
<a name="line197"></a> * is LTR.
<a name="line198"></a> * @type {RegExp}
<a name="line199"></a> * @private
<a name="line200"></a> */
<a name="line201"></a>goog.i18n.bidi.ltrRe_ = new RegExp(&#39;^[&#39; + goog.i18n.bidi.ltrChars_ + &#39;]&#39;);
<a name="line202"></a>
<a name="line203"></a>
<a name="line204"></a>/**
<a name="line205"></a> * Regular expression pattern to check if the first character in the string
<a name="line206"></a> * is RTL.
<a name="line207"></a> * @type {RegExp}
<a name="line208"></a> * @private
<a name="line209"></a> */
<a name="line210"></a>goog.i18n.bidi.rtlRe_ = new RegExp(&#39;^[&#39; + goog.i18n.bidi.rtlChars_ + &#39;]&#39;);
<a name="line211"></a>
<a name="line212"></a>
<a name="line213"></a>/**
<a name="line214"></a> * Check if the first character in the string is RTL or not.
<a name="line215"></a> * @param {string} str The given string that need to be tested.
<a name="line216"></a> * @return {boolean} Whether the first character in str is an RTL char.
<a name="line217"></a> */
<a name="line218"></a>goog.i18n.bidi.isRtlChar = function(str) {
<a name="line219"></a>  return goog.i18n.bidi.rtlRe_.test(str);
<a name="line220"></a>};
<a name="line221"></a>
<a name="line222"></a>
<a name="line223"></a>/**
<a name="line224"></a> * Check if the first character in the string is LTR or not.
<a name="line225"></a> * @param {string} str The given string that need to be tested.
<a name="line226"></a> * @return {boolean} Whether the first character in str is an LTR char.
<a name="line227"></a> */
<a name="line228"></a>goog.i18n.bidi.isLtrChar = function(str) {
<a name="line229"></a>  return goog.i18n.bidi.ltrRe_.test(str);
<a name="line230"></a>};
<a name="line231"></a>
<a name="line232"></a>
<a name="line233"></a>/**
<a name="line234"></a> * Check if the first character in the string is neutral or not.
<a name="line235"></a> * @param {string} str The given string that need to be tested.
<a name="line236"></a> * @return {boolean} Whether the first character in str is a neutral char.
<a name="line237"></a> */
<a name="line238"></a>goog.i18n.bidi.isNeutralChar = function(str) {
<a name="line239"></a>  return !goog.i18n.bidi.isLtrChar(str) &amp;&amp; !goog.i18n.bidi.isRtlChar(str);
<a name="line240"></a>};
<a name="line241"></a>
<a name="line242"></a>
<a name="line243"></a>/**
<a name="line244"></a> * Regular expressions to check if a piece of text if of LTR directionality
<a name="line245"></a> * on first character with strong directionality.
<a name="line246"></a> * @type {RegExp}
<a name="line247"></a> * @private
<a name="line248"></a> */
<a name="line249"></a>goog.i18n.bidi.ltrDirCheckRe_ = new RegExp(
<a name="line250"></a>    &#39;^[^&#39; + goog.i18n.bidi.rtlChars_ + &#39;]*[&#39; + goog.i18n.bidi.ltrChars_ + &#39;]&#39;);
<a name="line251"></a>
<a name="line252"></a>
<a name="line253"></a>/**
<a name="line254"></a> * Regular expressions to check if a piece of text if of RTL directionality
<a name="line255"></a> * on first character with strong directionality.
<a name="line256"></a> * @type {RegExp}
<a name="line257"></a> * @private
<a name="line258"></a> */
<a name="line259"></a>goog.i18n.bidi.rtlDirCheckRe_ = new RegExp(
<a name="line260"></a>    &#39;^[^&#39; + goog.i18n.bidi.ltrChars_ + &#39;]*[&#39; + goog.i18n.bidi.rtlChars_ + &#39;]&#39;);
<a name="line261"></a>
<a name="line262"></a>
<a name="line263"></a>/**
<a name="line264"></a> * Check whether the first strongly directional character (if any) is RTL.
<a name="line265"></a> * @param {string} str String being checked.
<a name="line266"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line267"></a> *     Default: false.
<a name="line268"></a> * @return {boolean} Whether RTL directionality is detected using the first
<a name="line269"></a> *     strongly-directional character method.
<a name="line270"></a> */
<a name="line271"></a>goog.i18n.bidi.startsWithRtl = function(str, opt_isHtml) {
<a name="line272"></a>  return goog.i18n.bidi.rtlDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
<a name="line273"></a>      str, opt_isHtml));
<a name="line274"></a>};
<a name="line275"></a>
<a name="line276"></a>
<a name="line277"></a>/**
<a name="line278"></a> * Check whether the first strongly directional character (if any) is RTL.
<a name="line279"></a> * @param {string} str String being checked.
<a name="line280"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line281"></a> *     Default: false.
<a name="line282"></a> * @return {boolean} Whether RTL directionality is detected using the first
<a name="line283"></a> *     strongly-directional character method.
<a name="line284"></a> * @deprecated Use startsWithRtl.
<a name="line285"></a> */
<a name="line286"></a>goog.i18n.bidi.isRtlText = goog.i18n.bidi.startsWithRtl;
<a name="line287"></a>
<a name="line288"></a>
<a name="line289"></a>/**
<a name="line290"></a> * Check whether the first strongly directional character (if any) is LTR.
<a name="line291"></a> * @param {string} str String being checked.
<a name="line292"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line293"></a> *     Default: false.
<a name="line294"></a> * @return {boolean} Whether LTR directionality is detected using the first
<a name="line295"></a> *     strongly-directional character method.
<a name="line296"></a> */
<a name="line297"></a>goog.i18n.bidi.startsWithLtr = function(str, opt_isHtml) {
<a name="line298"></a>  return goog.i18n.bidi.ltrDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
<a name="line299"></a>      str, opt_isHtml));
<a name="line300"></a>};
<a name="line301"></a>
<a name="line302"></a>
<a name="line303"></a>/**
<a name="line304"></a> * Check whether the first strongly directional character (if any) is LTR.
<a name="line305"></a> * @param {string} str String being checked.
<a name="line306"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line307"></a> *     Default: false.
<a name="line308"></a> * @return {boolean} Whether LTR directionality is detected using the first
<a name="line309"></a> *     strongly-directional character method.
<a name="line310"></a> * @deprecated Use startsWithLtr.
<a name="line311"></a> */
<a name="line312"></a>goog.i18n.bidi.isLtrText = goog.i18n.bidi.startsWithLtr;
<a name="line313"></a>
<a name="line314"></a>
<a name="line315"></a>/**
<a name="line316"></a> * Regular expression to check if a string looks like something that must
<a name="line317"></a> * always be LTR even in RTL text, e.g. a URL. When estimating the
<a name="line318"></a> * directionality of text containing these, we treat these as weakly LTR,
<a name="line319"></a> * like numbers.
<a name="line320"></a> * @type {RegExp}
<a name="line321"></a> * @private
<a name="line322"></a> */
<a name="line323"></a>goog.i18n.bidi.isRequiredLtrRe_ = /^http:\/\/.*/;
<a name="line324"></a>
<a name="line325"></a>
<a name="line326"></a>/**
<a name="line327"></a> * Check whether the input string either contains no strongly directional
<a name="line328"></a> * characters or looks like a url.
<a name="line329"></a> * @param {string} str String being checked.
<a name="line330"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line331"></a> *     Default: false.
<a name="line332"></a> * @return {boolean} Whether neutral directionality is detected.
<a name="line333"></a> */
<a name="line334"></a>goog.i18n.bidi.isNeutralText = function(str, opt_isHtml) {
<a name="line335"></a>  str = goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml);
<a name="line336"></a>  return goog.i18n.bidi.isRequiredLtrRe_.test(str) ||
<a name="line337"></a>      !goog.i18n.bidi.hasAnyLtr(str) &amp;&amp; !goog.i18n.bidi.hasAnyRtl(str);
<a name="line338"></a>};
<a name="line339"></a>
<a name="line340"></a>
<a name="line341"></a>/**
<a name="line342"></a> * Regular expressions to check if the last strongly-directional character in a
<a name="line343"></a> * piece of text is LTR.
<a name="line344"></a> * @type {RegExp}
<a name="line345"></a> * @private
<a name="line346"></a> */
<a name="line347"></a>goog.i18n.bidi.ltrExitDirCheckRe_ = new RegExp(
<a name="line348"></a>    &#39;[&#39; + goog.i18n.bidi.ltrChars_ + &#39;][^&#39; + goog.i18n.bidi.rtlChars_ + &#39;]*$&#39;);
<a name="line349"></a>
<a name="line350"></a>
<a name="line351"></a>/**
<a name="line352"></a> * Regular expressions to check if the last strongly-directional character in a
<a name="line353"></a> * piece of text is RTL.
<a name="line354"></a> * @type {RegExp}
<a name="line355"></a> * @private
<a name="line356"></a> */
<a name="line357"></a>goog.i18n.bidi.rtlExitDirCheckRe_ = new RegExp(
<a name="line358"></a>    &#39;[&#39; + goog.i18n.bidi.rtlChars_ + &#39;][^&#39; + goog.i18n.bidi.ltrChars_ + &#39;]*$&#39;);
<a name="line359"></a>
<a name="line360"></a>
<a name="line361"></a>/**
<a name="line362"></a> * Check if the exit directionality a piece of text is LTR, i.e. if the last
<a name="line363"></a> * strongly-directional character in the string is LTR.
<a name="line364"></a> * @param {string} str String being checked.
<a name="line365"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line366"></a> *     Default: false.
<a name="line367"></a> * @return {boolean} Whether LTR exit directionality was detected.
<a name="line368"></a> */
<a name="line369"></a>goog.i18n.bidi.endsWithLtr = function(str, opt_isHtml) {
<a name="line370"></a>  return goog.i18n.bidi.ltrExitDirCheckRe_.test(
<a name="line371"></a>      goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
<a name="line372"></a>};
<a name="line373"></a>
<a name="line374"></a>
<a name="line375"></a>/**
<a name="line376"></a> * Check if the exit directionality a piece of text is LTR, i.e. if the last
<a name="line377"></a> * strongly-directional character in the string is LTR.
<a name="line378"></a> * @param {string} str String being checked.
<a name="line379"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line380"></a> *     Default: false.
<a name="line381"></a> * @return {boolean} Whether LTR exit directionality was detected.
<a name="line382"></a> * @deprecated Use endsWithLtr.
<a name="line383"></a> */
<a name="line384"></a>goog.i18n.bidi.isLtrExitText = goog.i18n.bidi.endsWithLtr;
<a name="line385"></a>
<a name="line386"></a>
<a name="line387"></a>/**
<a name="line388"></a> * Check if the exit directionality a piece of text is RTL, i.e. if the last
<a name="line389"></a> * strongly-directional character in the string is RTL.
<a name="line390"></a> * @param {string} str String being checked.
<a name="line391"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line392"></a> *     Default: false.
<a name="line393"></a> * @return {boolean} Whether RTL exit directionality was detected.
<a name="line394"></a> */
<a name="line395"></a>goog.i18n.bidi.endsWithRtl = function(str, opt_isHtml) {
<a name="line396"></a>  return goog.i18n.bidi.rtlExitDirCheckRe_.test(
<a name="line397"></a>      goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
<a name="line398"></a>};
<a name="line399"></a>
<a name="line400"></a>
<a name="line401"></a>/**
<a name="line402"></a> * Check if the exit directionality a piece of text is RTL, i.e. if the last
<a name="line403"></a> * strongly-directional character in the string is RTL.
<a name="line404"></a> * @param {string} str String being checked.
<a name="line405"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line406"></a> *     Default: false.
<a name="line407"></a> * @return {boolean} Whether RTL exit directionality was detected.
<a name="line408"></a> * @deprecated Use endsWithRtl.
<a name="line409"></a> */
<a name="line410"></a>goog.i18n.bidi.isRtlExitText = goog.i18n.bidi.endsWithRtl;
<a name="line411"></a>
<a name="line412"></a>
<a name="line413"></a>/**
<a name="line414"></a> * A regular expression for matching right-to-left language codes.
<a name="line415"></a> * See {@link #isRtlLanguage} for the design.
<a name="line416"></a> * @type {RegExp}
<a name="line417"></a> * @private
<a name="line418"></a> */
<a name="line419"></a>goog.i18n.bidi.rtlLocalesRe_ = new RegExp(
<a name="line420"></a>    &#39;^(ar|dv|he|iw|fa|nqo|ps|sd|ug|ur|yi|.*[-_](Arab|Hebr|Thaa|Nkoo|Tfng))&#39; +
<a name="line421"></a>    &#39;(?!.*[-_](Latn|Cyrl)($|-|_))($|-|_)&#39;);
<a name="line422"></a>
<a name="line423"></a>
<a name="line424"></a>/**
<a name="line425"></a> * Check if a BCP 47 / III language code indicates an RTL language, i.e. either:
<a name="line426"></a> * - a language code explicitly specifying one of the right-to-left scripts,
<a name="line427"></a> *   e.g. &quot;az-Arab&quot;, or&lt;p&gt;
<a name="line428"></a> * - a language code specifying one of the languages normally written in a
<a name="line429"></a> *   right-to-left script, e.g. &quot;fa&quot; (Farsi), except ones explicitly specifying
<a name="line430"></a> *   Latin or Cyrillic script (which are the usual LTR alternatives).&lt;p&gt;
<a name="line431"></a> * The list of right-to-left scripts appears in the 100-199 range in
<a name="line432"></a> * http://www.unicode.org/iso15924/iso15924-num.html, of which Arabic and
<a name="line433"></a> * Hebrew are by far the most widely used. We also recognize Thaana, N&#39;Ko, and
<a name="line434"></a> * Tifinagh, which also have significant modern usage. The rest (Syriac,
<a name="line435"></a> * Samaritan, Mandaic, etc.) seem to have extremely limited or no modern usage
<a name="line436"></a> * and are not recognized to save on code size.
<a name="line437"></a> * The languages usually written in a right-to-left script are taken as those
<a name="line438"></a> * with Suppress-Script: Hebr|Arab|Thaa|Nkoo|Tfng  in
<a name="line439"></a> * http://www.iana.org/assignments/language-subtag-registry,
<a name="line440"></a> * as well as Sindhi (sd) and Uyghur (ug).
<a name="line441"></a> * Other subtags of the language code, e.g. regions like EG (Egypt), are
<a name="line442"></a> * ignored.
<a name="line443"></a> * @param {string} lang BCP 47 (a.k.a III) language code.
<a name="line444"></a> * @return {boolean} Whether the language code is an RTL language.
<a name="line445"></a> */
<a name="line446"></a>goog.i18n.bidi.isRtlLanguage = function(lang) {
<a name="line447"></a>  return goog.i18n.bidi.rtlLocalesRe_.test(lang);
<a name="line448"></a>};
<a name="line449"></a>
<a name="line450"></a>
<a name="line451"></a>/**
<a name="line452"></a> * Regular expression for bracket guard replacement in html.
<a name="line453"></a> * @type {RegExp}
<a name="line454"></a> * @private
<a name="line455"></a> */
<a name="line456"></a>goog.i18n.bidi.bracketGuardHtmlRe_ =
<a name="line457"></a>    /(\([^\)]*\))|(\[[^\]]*\])|({[^}]*})|(&amp;lt;[^&amp;]*&amp;gt;)/g;
<a name="line458"></a>
<a name="line459"></a>
<a name="line460"></a>/**
<a name="line461"></a> * Regular expression for bracket guard replacement in text.
<a name="line462"></a> * @type {RegExp}
<a name="line463"></a> * @private
<a name="line464"></a> */
<a name="line465"></a>goog.i18n.bidi.bracketGuardTextRe_ =
<a name="line466"></a>    /(\([^\)]*\))|(\[[^\]]*\])|({[^}]*})|(&lt;[^&gt;]*&gt;)/g;
<a name="line467"></a>
<a name="line468"></a>
<a name="line469"></a>/**
<a name="line470"></a> * Apply bracket guard using html span tag. This is to address the problem of
<a name="line471"></a> * messy bracket display frequently happens in RTL layout.
<a name="line472"></a> * @param {string} s The string that need to be processed.
<a name="line473"></a> * @return {string} The processed string, with all bracket guarded.
<a name="line474"></a> */
<a name="line475"></a>goog.i18n.bidi.guardBracketInHtml = function(s) {
<a name="line476"></a>  if (goog.i18n.bidi.hasAnyRtl(s)) {
<a name="line477"></a>    return s.replace(goog.i18n.bidi.bracketGuardHtmlRe_,
<a name="line478"></a>        &#39;&lt;span dir=rtl&gt;$&amp;&lt;/span&gt;&#39;);
<a name="line479"></a>  }
<a name="line480"></a>  return s.replace(goog.i18n.bidi.bracketGuardHtmlRe_,
<a name="line481"></a>      &#39;&lt;span dir=ltr&gt;$&amp;&lt;/span&gt;&#39;);
<a name="line482"></a>};
<a name="line483"></a>
<a name="line484"></a>
<a name="line485"></a>/**
<a name="line486"></a> * Apply bracket guard using LRM and RLM. This is to address the problem of
<a name="line487"></a> * messy bracket display frequently happens in RTL layout.
<a name="line488"></a> * This version works for both plain text and html. But it does not work as
<a name="line489"></a> * good as guardBracketInHtml in some cases.
<a name="line490"></a> * @param {string} s The string that need to be processed.
<a name="line491"></a> * @return {string} The processed string, with all bracket guarded.
<a name="line492"></a> */
<a name="line493"></a>goog.i18n.bidi.guardBracketInText = function(s) {
<a name="line494"></a>  var mark = goog.i18n.bidi.hasAnyRtl(s) ? goog.i18n.bidi.Format.RLM :
<a name="line495"></a>      goog.i18n.bidi.Format.LRM;
<a name="line496"></a>  return s.replace(goog.i18n.bidi.bracketGuardTextRe_, mark + &#39;$&amp;&#39; + mark);
<a name="line497"></a>};
<a name="line498"></a>
<a name="line499"></a>/**
<a name="line500"></a> * Enforce the html snippet in RTL directionality regardless overall context.
<a name="line501"></a> * If the html piece was enclosed by tag, dir will be applied to existing
<a name="line502"></a> * tag, otherwise a span tag will be added as wrapper. For this reason, if
<a name="line503"></a> * html snippet start with with tag, this tag must enclose the whole piece. If
<a name="line504"></a> * the tag already has a dir specified, this new one will override existing
<a name="line505"></a> * one in behavior (tested on FF and IE).
<a name="line506"></a> * @param {string} html The string that need to be processed.
<a name="line507"></a> * @return {string} The processed string, with directionality enforced to RTL.
<a name="line508"></a> */
<a name="line509"></a>goog.i18n.bidi.enforceRtlInHtml = function(html) {
<a name="line510"></a>  if (html.charAt(0) == &#39;&lt;&#39;) {
<a name="line511"></a>    return html.replace(/&lt;\w+/, &#39;$&amp; dir=rtl&#39;);
<a name="line512"></a>  }
<a name="line513"></a>  // &#39;\n&#39; is important for FF so that it won&#39;t incorrectly merge span groups
<a name="line514"></a>  return &#39;\n&lt;span dir=rtl&gt;&#39; + html + &#39;&lt;/span&gt;&#39;;
<a name="line515"></a>};
<a name="line516"></a>
<a name="line517"></a>/**
<a name="line518"></a> * Enforce RTL on both end of the given text piece using unicode BiDi formatting
<a name="line519"></a> * characters RLE and PDF.
<a name="line520"></a> * @param {string} text The piece of text that need to be wrapped.
<a name="line521"></a> * @return {string} The wrapped string after process.
<a name="line522"></a> */
<a name="line523"></a>goog.i18n.bidi.enforceRtlInText = function(text) {
<a name="line524"></a>  return goog.i18n.bidi.Format.RLE + text + goog.i18n.bidi.Format.PDF;
<a name="line525"></a>};
<a name="line526"></a>
<a name="line527"></a>/**
<a name="line528"></a> * Enforce the html snippet in RTL directionality regardless overall context.
<a name="line529"></a> * If the html piece was enclosed by tag, dir will be applied to existing
<a name="line530"></a> * tag, otherwise a span tag will be added as wrapper. For this reason, if
<a name="line531"></a> * html snippet start with with tag, this tag must enclose the whole piece. If
<a name="line532"></a> * the tag already has a dir specified, this new one will override existing
<a name="line533"></a> * one in behavior (tested on FF and IE).
<a name="line534"></a> * @param {string} html The string that need to be processed.
<a name="line535"></a> * @return {string} The processed string, with directionality enforced to RTL.
<a name="line536"></a> */
<a name="line537"></a>goog.i18n.bidi.enforceLtrInHtml = function(html) {
<a name="line538"></a>  if (html.charAt(0) == &#39;&lt;&#39;) {
<a name="line539"></a>    return html.replace(/&lt;\w+/, &#39;$&amp; dir=ltr&#39;);
<a name="line540"></a>  }
<a name="line541"></a>  // &#39;\n&#39; is important for FF so that it won&#39;t incorrectly merge span groups
<a name="line542"></a>  return &#39;\n&lt;span dir=ltr&gt;&#39; + html + &#39;&lt;/span&gt;&#39;;
<a name="line543"></a>};
<a name="line544"></a>
<a name="line545"></a>/**
<a name="line546"></a> * Enforce LTR on both end of the given text piece using unicode BiDi formatting
<a name="line547"></a> * characters LRE and PDF.
<a name="line548"></a> * @param {string} text The piece of text that need to be wrapped.
<a name="line549"></a> * @return {string} The wrapped string after process.
<a name="line550"></a> */
<a name="line551"></a>goog.i18n.bidi.enforceLtrInText = function(text) {
<a name="line552"></a>  return goog.i18n.bidi.Format.LRE + text + goog.i18n.bidi.Format.PDF;
<a name="line553"></a>};
<a name="line554"></a>
<a name="line555"></a>/**
<a name="line556"></a> * Regular expression to find dimensions such as &quot;padding: .3 0.4ex 5px 6;&quot;
<a name="line557"></a> * @type {RegExp}
<a name="line558"></a> * @private
<a name="line559"></a> */
<a name="line560"></a>goog.i18n.bidi.dimensionsRe_ =
<a name="line561"></a>     /:\s*([.\d][.\w]*)\s+([.\d][.\w]*)\s+([.\d][.\w]*)\s+([.\d][.\w]*)/g;
<a name="line562"></a>
<a name="line563"></a>
<a name="line564"></a>/**
<a name="line565"></a> * Regular expression for left.
<a name="line566"></a> * @type {RegExp}
<a name="line567"></a> * @private
<a name="line568"></a> */
<a name="line569"></a>goog.i18n.bidi.leftRe_ = /left/gi;
<a name="line570"></a>
<a name="line571"></a>
<a name="line572"></a>/**
<a name="line573"></a> * Regular expression for right.
<a name="line574"></a> * @type {RegExp}
<a name="line575"></a> * @private
<a name="line576"></a> */
<a name="line577"></a>goog.i18n.bidi.rightRe_ = /right/gi;
<a name="line578"></a>
<a name="line579"></a>
<a name="line580"></a>/**
<a name="line581"></a> * Placeholder regular expression for swapping.
<a name="line582"></a> * @type {RegExp}
<a name="line583"></a> * @private
<a name="line584"></a> */
<a name="line585"></a>goog.i18n.bidi.tempRe_ = /%%%%/g;
<a name="line586"></a>
<a name="line587"></a>
<a name="line588"></a>/**
<a name="line589"></a> * Swap location parameters and &#39;left&#39;/&#39;right&#39; in CSS specification. The
<a name="line590"></a> * processed string will be suited for RTL layout. Though this function can
<a name="line591"></a> * cover most cases, there are always exceptions. It is suggested to put
<a name="line592"></a> * those exceptions in separate group of CSS string.
<a name="line593"></a> * @param {string} cssStr CSS spefication string.
<a name="line594"></a> * @return {string} Processed CSS specification string.
<a name="line595"></a> */
<a name="line596"></a>goog.i18n.bidi.mirrorCSS = function(cssStr) {
<a name="line597"></a>  return cssStr.
<a name="line598"></a>    // reverse dimensions
<a name="line599"></a>    replace(goog.i18n.bidi.dimensionsRe_, &#39;:$1 $4 $3 $2&#39;).
<a name="line600"></a>    replace(goog.i18n.bidi.leftRe_, &#39;%%%%&#39;).          // swap left and right
<a name="line601"></a>    replace(goog.i18n.bidi.rightRe_, goog.i18n.bidi.LEFT).
<a name="line602"></a>    replace(goog.i18n.bidi.tempRe_, goog.i18n.bidi.RIGHT);
<a name="line603"></a>};
<a name="line604"></a>
<a name="line605"></a>
<a name="line606"></a>/**
<a name="line607"></a> * Regular expression for hebrew double quote substitution, finding quote
<a name="line608"></a> * directly after hebrew characters.
<a name="line609"></a> * @type {RegExp}
<a name="line610"></a> * @private
<a name="line611"></a> */
<a name="line612"></a>goog.i18n.bidi.doubleQuoteSubstituteRe_ = /([\u0591-\u05f2])&quot;/g;
<a name="line613"></a>
<a name="line614"></a>
<a name="line615"></a>/**
<a name="line616"></a> * Regular expression for hebrew single quote substitution, finding quote
<a name="line617"></a> * directly after hebrew characters.
<a name="line618"></a> * @type {RegExp}
<a name="line619"></a> * @private
<a name="line620"></a> */
<a name="line621"></a>goog.i18n.bidi.singleQuoteSubstituteRe_ = /([\u0591-\u05f2])&#39;/g;
<a name="line622"></a>
<a name="line623"></a>
<a name="line624"></a>/**
<a name="line625"></a> * Replace the double and single quote directly after a Hebrew character with
<a name="line626"></a> * GERESH and GERSHAYIM. In such case, most likely that&#39;s user intention.
<a name="line627"></a> * @param {string} str String that need to be processed.
<a name="line628"></a> * @return {string} Processed string with double/single quote replaced.
<a name="line629"></a> */
<a name="line630"></a>goog.i18n.bidi.normalizeHebrewQuote = function(str) {
<a name="line631"></a>  return str.
<a name="line632"></a>    replace(goog.i18n.bidi.doubleQuoteSubstituteRe_, &#39;$1\u05f4&#39;).
<a name="line633"></a>    replace(goog.i18n.bidi.singleQuoteSubstituteRe_, &#39;$1\u05f3&#39;);
<a name="line634"></a>};
<a name="line635"></a>
<a name="line636"></a>
<a name="line637"></a>/**
<a name="line638"></a> * Regular expression to split a string into &quot;words&quot; for directionality
<a name="line639"></a> * estimation based on relative word counts.
<a name="line640"></a> * @type {RegExp}
<a name="line641"></a> * @private
<a name="line642"></a> */
<a name="line643"></a>goog.i18n.bidi.wordSeparatorRe_ = /\s+/;
<a name="line644"></a>
<a name="line645"></a>
<a name="line646"></a>/**
<a name="line647"></a> * Regular expression to check if a string contains any numerals. Used to
<a name="line648"></a> * differentiate between completely neutral strings and those containing
<a name="line649"></a> * numbers, which are weakly LTR.
<a name="line650"></a> * @type {RegExp}
<a name="line651"></a> * @private
<a name="line652"></a> */
<a name="line653"></a>goog.i18n.bidi.hasNumeralsRe_ = /\d/;
<a name="line654"></a>
<a name="line655"></a>
<a name="line656"></a>/**
<a name="line657"></a> * This constant controls threshold of RTL directionality.
<a name="line658"></a> * @type {number}
<a name="line659"></a> * @private
<a name="line660"></a> */
<a name="line661"></a>goog.i18n.bidi.rtlDetectionThreshold_ = 0.40;
<a name="line662"></a>
<a name="line663"></a>
<a name="line664"></a>/**
<a name="line665"></a> * Estimates the directionality of a string based on relative word counts.
<a name="line666"></a> * If the number of RTL words is above a certain percentage of the total number
<a name="line667"></a> * of strongly directional words, returns RTL.
<a name="line668"></a> * Otherwise, if any words are strongly or weakly LTR, returns LTR.
<a name="line669"></a> * Otherwise, returns UNKNOWN, which is used to mean &quot;neutral&quot;.
<a name="line670"></a> * Numbers are counted as weakly LTR.
<a name="line671"></a> * @param {string} str The string to be checked.
<a name="line672"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line673"></a> *     Default: false.
<a name="line674"></a> * @return {goog.i18n.bidi.Dir} Estimated overall directionality of {@code str}.
<a name="line675"></a> */
<a name="line676"></a>goog.i18n.bidi.estimateDirection = function(str, opt_isHtml) {
<a name="line677"></a>  var rtlCount = 0;
<a name="line678"></a>  var totalCount = 0;
<a name="line679"></a>  var hasWeaklyLtr = false;
<a name="line680"></a>  var tokens = goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml).
<a name="line681"></a>      split(goog.i18n.bidi.wordSeparatorRe_);
<a name="line682"></a>  for (var i = 0; i &lt; tokens.length; i++) {
<a name="line683"></a>    var token = tokens[i];
<a name="line684"></a>    if (goog.i18n.bidi.startsWithRtl(token)) {
<a name="line685"></a>      rtlCount++;
<a name="line686"></a>      totalCount++;
<a name="line687"></a>    } else if (goog.i18n.bidi.isRequiredLtrRe_.test(token)) {
<a name="line688"></a>      hasWeaklyLtr = true;
<a name="line689"></a>    } else if (goog.i18n.bidi.hasAnyLtr(token)) {
<a name="line690"></a>      totalCount++;
<a name="line691"></a>    } else if (goog.i18n.bidi.hasNumeralsRe_.test(token)) {
<a name="line692"></a>      hasWeaklyLtr = true;
<a name="line693"></a>    }
<a name="line694"></a>  }
<a name="line695"></a>
<a name="line696"></a>  return totalCount == 0 ?
<a name="line697"></a>      (hasWeaklyLtr ? goog.i18n.bidi.Dir.LTR : goog.i18n.bidi.Dir.UNKNOWN) :
<a name="line698"></a>      (rtlCount / totalCount &gt; goog.i18n.bidi.rtlDetectionThreshold_ ?
<a name="line699"></a>          goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR);
<a name="line700"></a>};
<a name="line701"></a>
<a name="line702"></a>
<a name="line703"></a>/**
<a name="line704"></a> * Check the directionality of a piece of text, return true if the piece of
<a name="line705"></a> * text should be laid out in RTL direction.
<a name="line706"></a> * @param {string} str The piece of text that need to be detected.
<a name="line707"></a> * @param {boolean} opt_isHtml Whether str is HTML / HTML-escaped.
<a name="line708"></a> *     Default: false.
<a name="line709"></a> * @return {boolean} Whether this piece of text should be laid out in RTL.
<a name="line710"></a> */
<a name="line711"></a>goog.i18n.bidi.detectRtlDirectionality = function(str, opt_isHtml) {
<a name="line712"></a>  return goog.i18n.bidi.estimateDirection(str, opt_isHtml) ==
<a name="line713"></a>      goog.i18n.bidi.Dir.RTL;
<a name="line714"></a>};
<a name="line715"></a>
<a name="line716"></a>
<a name="line717"></a>/**
<a name="line718"></a> * Sets text input element&#39;s directionality and text alignment based on a
<a name="line719"></a> * given directionality.
<a name="line720"></a> * @param {Element} element Input field element to set directionality to.
<a name="line721"></a> * @param {goog.i18n.bidi.Dir|number|boolean} dir Desired directionality, given
<a name="line722"></a> *     in one of the following formats:
<a name="line723"></a> *     1. A goog.i18n.bidi.Dir constant.
<a name="line724"></a> *     2. A number (positive = LRT, negative = RTL, 0 = unknown).
<a name="line725"></a> *     3. A boolean (true = RTL, false = LTR).
<a name="line726"></a> */
<a name="line727"></a>goog.i18n.bidi.setElementDirAndAlign = function(element, dir) {
<a name="line728"></a>  if (element &amp;&amp;
<a name="line729"></a>      (dir = goog.i18n.bidi.toDir(dir)) != goog.i18n.bidi.Dir.UNKNOWN) {
<a name="line730"></a>    element.style.textAlign = dir == goog.i18n.bidi.Dir.RTL ? &#39;right&#39; : &#39;left&#39;;
<a name="line731"></a>    element.dir = dir == goog.i18n.bidi.Dir.RTL ? &#39;rtl&#39; : &#39;ltr&#39;;
<a name="line732"></a>  }
<a name="line733"></a>};
</pre>


</body>
</html>
